package com.itcoon.cloud.framework.config;/**
 * @author Athric Yu
 * 2024/11/12
 **/

import com.itcoon.cloud.framework.properties.TemporalPatternConfigProperties;
import com.itcoon.cloud.framework.temporal.*;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 *
 * @author Athric Yu
 * 2024/11/12
 **/
@EnableConfigurationProperties(TemporalPatternConfigProperties.class)
public class TemporalPatternConfig {

    private static final Map<Class<?>, Map<Class<? extends Temporal>, AbstractConverter<?, ? extends Temporal>>> TEMPORAL_MAP = new HashMap<>();

    static {
        Map<Class<? extends Temporal>, AbstractConverter<?, ? extends Temporal>> stringTemporalMap = new HashMap<>();
        TEMPORAL_MAP.put(String.class, stringTemporalMap);
        Map<Class<? extends Temporal>, AbstractConverter<?, ? extends Temporal>> longTemporalMap = new HashMap<>();
        TEMPORAL_MAP.put(Long.class, longTemporalMap);
    }


    private final TemporalPatternConfigProperties properties;
    public TemporalPatternConfig(TemporalPatternConfigProperties configProperties){
        this.properties = configProperties;
        for (TemporalPatternConfigProperties.TemporalSerialization<?, ?> temporalSerialization : configProperties.getTemporalSerializations()) {
           Map<Class<? extends Temporal>, AbstractConverter<?, ? extends Temporal>> temporalMap =  TEMPORAL_MAP.get(temporalSerialization.getSerialType());
           if(String.class.equals(temporalSerialization.getSerialType())){
               if(ZonedDateTime.class.equals(temporalSerialization.getTemporalType())){
                   temporalMap.put(ZonedDateTime.class, new StringZonedDateTimeConverter((TemporalPatternConfigProperties.TemporalSerialization<String, ZonedDateTime>) temporalSerialization));
               }
               if(LocalDateTime.class.equals(temporalSerialization.getTemporalType())){
                   temporalMap.put(LocalDateTime.class, new StringLocalDateTimeConverter((TemporalPatternConfigProperties.TemporalSerialization<String, LocalDateTime>) temporalSerialization));
               }
               if(LocalDate.class.equals(temporalSerialization.getTemporalType())){
                   temporalMap.put(LocalDate.class, new StringLocalDateConverter((TemporalPatternConfigProperties.TemporalSerialization<String, LocalDate>) temporalSerialization));
               }
           }
            if(Long.class.equals(temporalSerialization.getSerialType())){
                if(ZonedDateTime.class.equals(temporalSerialization.getTemporalType())){
                    temporalMap.put(ZonedDateTime.class, new LongZonedDateTimeConverter((TemporalPatternConfigProperties.TemporalSerialization<Long, ZonedDateTime>) temporalSerialization));
                }
                if(LocalDateTime.class.equals(temporalSerialization.getTemporalType())){
                    temporalMap.put(LocalDateTime.class, new LongLocalDateTimeConverter((TemporalPatternConfigProperties.TemporalSerialization<Long, LocalDateTime>) temporalSerialization));
                }
                if(LocalDate.class.equals(temporalSerialization.getTemporalType())){
                    temporalMap.put(LocalDate.class, new LongLocalDateConverter((TemporalPatternConfigProperties.TemporalSerialization<Long, LocalDate>) temporalSerialization));
                }
            }
        }
    }

    public static <S extends Serializable, T extends Temporal>AbstractConverter<S, T> getConverter(Class<S> serialType, Class<?> temporalType){
        return (AbstractConverter<S, T>) TEMPORAL_MAP.get(serialType).get(temporalType);
    }

    public static <S extends Serializable, T extends Temporal> List<AbstractConverter<S, T>> getConverters(){
        List<AbstractConverter<S, T>> abstractConverters = new ArrayList<>();
        for (Map<Class<? extends Temporal>, AbstractConverter<?, ? extends Temporal>> map : TEMPORAL_MAP.values()) {
            for (AbstractConverter<?, ? extends Temporal> value : map.values()) {
                abstractConverters.add((AbstractConverter<S, T>) value);
            }
        }
        return abstractConverters;
    }

    public TemporalPatternConfigProperties getProperties() {
        return properties;
    }
}
